import qs from "qs";
import WebSocket, { WebSocketServer } from "ws";
import { findBestMove } from "./ai.js";

const webSocket = new WebSocketServer({
  port: 3000,
});

webSocket.on("connection", function (ws, req) {
  // 解析客户端的uid
  const query = qs.parse(req.url.split("?")[1]);
  // 给每个客户端连接添加一个uid
  ws.uid = query.uid;
  console.log(`${ws.uid} 上线了`);

  // 当有偶数个用户连接时，进行玩家匹配,随机决定先后手
  matchPlayers(Array.from(webSocket.clients.values()));

  // 监听客户端发送的消息
  ws.on("message", function (message) {
    // logger.info(`[SERVER] Received: ${message}`);

    // 不做这样的转换,会以二进制数据发送
    let msgData = JSON.parse(message);

    if (["board"].includes(msgData.type)) {
      // 轮哪一方下棋了的切换逻辑
      msgData.role = msgData.role === "front" ? "back" : "front";

      if (msgData.role === "back") {
        const bestMove = findBestMove(msgData.content, 10, msgData.role);
        console.log("bestMove", bestMove);
        msgData.aiPlaceIndex = bestMove;
        // msgData.content[bestMove] = msgData.role;
      }
    }

    // 给所有的客户端广播消息(发消息的客户端除外)
    webSocket.clients.forEach(function each(client) {
      // 只给同组成员推送棋局消息
      if ([ws.uid, ws.partnerUid].includes(client.uid) && client.readyState === WebSocket.OPEN) {
        client.send(JSON.stringify(msgData));
      }
    });
  });

  // 断开监听
  ws.on("close", (code, reason) => {
    console.log(`有一方掉线了:`);
    console.table({ 掉线方Id: ws.uid, 对手方Id: 2, 出错代码: code });
    // 通知五子棋对手方，己方掉线了
    broadcastToOthers(ws, "对手下线了");
  });
});

/**
 * 匹配五子棋玩家
 * @param {长链接实例} webSocket
 */
function matchPlayers(clients) {
  if (clients.length % 2 === 0 && clients.length >= 2) {
    // 先后手随机序号计算
    const frontPlayerIndex = Math.floor(Math.random() * 2);
    const backPlayerIndex = 1 - frontPlayerIndex;

    const matchPlayer = clients.slice(-2);

    // 给随机生成的先后手添加配对成员id
    matchPlayer[frontPlayerIndex].partnerUid = matchPlayer[backPlayerIndex].uid;
    matchPlayer[backPlayerIndex].partnerUid = matchPlayer[frontPlayerIndex].uid;

    console.log(`匹配成功的一对玩家ID:`);
    console.table([{ uid: matchPlayer[frontPlayerIndex].uid }, { uid: matchPlayer[backPlayerIndex].uid }]);
    // 给同组成员分别推送给自己随机设定的角色
    matchPlayer[frontPlayerIndex].send(
      JSON.stringify({
        type: "role",
        role: "front",
      })
    );

    matchPlayer[backPlayerIndex].send(
      JSON.stringify({
        type: "role",
        role: "back",
      })
    );
  }
}

// 通知五子棋对手方,连接断开
function broadcastToOthers(closeWs, message) {
  webSocket.clients.forEach((client) => {
    if (client.uid === closeWs.partnerUid && client.readyState === WebSocket.OPEN) {
      client.send(JSON.stringify({ type: "disconnect", disconnect: message }));
    }
  });
}
